package com.atguyigu.codesday01.Lock8Demo;

import java.io.InterruptedIOException;
import java.util.concurrent.TimeUnit;
                    /*7 有1个静态同步方法，有1个普通同步方法,有1部手机，请问先打印邮件还是短信？

                       答  -----SMS
                           ------Email

                       8 有1个静态同步方法，有1个普通同步方法,有2部手机，请问先打印邮件还是短信？
                         答  -----SMS
                           ------Email


                   总结 ： 当一个线程试图访问同步代码时它首先必须得到锁，退出或抛出异常时必须释放锁。

  所有的普通同步方法用的都是同一把锁——实例对象本身，，就是new出来的具体实例对象本身
 也就是说如果一个实例对象的普通同步方法获取锁后，该实例对象的其他普通同步方法必须等待获取锁的方法释放锁后才能获取锁，
 可是别的实例对象的普通同步方法因为跟该实例对象的普通同步方法用的是不同的锁，所以不用等待该实例对象已获取锁的普通
  同步方法释放锁就可以获取他们自己的锁。

 所有的静态同步方法用的也是同一把锁——类对象本身，就是我们说过的唯一模板Class
  具体实例对象this和唯一模板Class，这两把锁是两个不同的对象，所以静态同步方法与普通同步方法之间是不会有竞态条件的。
 但是一旦一个静态同步方法获取锁后，其他的静态同步方法都必须等待该方法释放锁后才能获取锁 *


 synchronized是实现同步的基础：Java中的每一个对象都可以作为锁。
  具体表现为以下3种形式。
    作用于实例方法，当前实例加锁，进入同步代码前要获得当前实例的锁；
   作用于静态方法，当前类加锁，进去同步代码前要获得当前类对象的锁；
     作用于代码块，对括号里配置的对象加锁。
  */


class Phone04 {
    public static synchronized void sendEmail() throws Exception {
        TimeUnit.SECONDS.sleep(4);
        System.out.println("------Email");
    }
    public  synchronized void sendSMS() throws Exception {
        System.out.println("-----SMS");
    }
    public void hello()
    {
        System.out.println("-----hello");
    }

}


public class Demo4 {

    public static void main(String[] args) throws InterruptedIOException, InterruptedException {

        Phone04 phonea=new Phone04();
        Phone04 phoneb=new Phone04();

        new Thread(() -> {
            try {
               phonea.sendEmail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "t1").start();

       Thread.sleep(10);

        new Thread(() -> {
            try {

                //phonea.sendSMS ();
                phoneb.sendSMS();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "t2").start();


    }


}
